/*
 * demo1.cpp
 *
 *  Created on: 2012-8-20
 *      Author: huangyansheng
 */

#include <iostream>
#include <gtest/gtest.h>
//增加gmock的依赖
#include <gmock/gmock.h>
using namespace ::testing;

using namespace std;

//面向抽象编程
class BaseProduct_9 {
public:
	virtual int getPrice(int id);
//	~BaseProduct_9(){};
};
int BaseProduct_9::getPrice(int id){
	return id;
}

//产品实现
class Product_9 : public BaseProduct_9{
public:
	Product_9(){};
	int getPrice(int id);
	~Product_9(){};
};
//根据商品的id，获取商品的价格
int Product_9::getPrice(int id) {
	if (id == 1)
		return 10;
	if (id == 2)
		return 20;
	if (id == 5)
		return 50;
	if (id == 10)
		return 100;
	if (id == 1001)
		return 0;
	if (id > 10000)
		return -1;
	return -1;
}

class Shop_9 {
public:
	BaseProduct_9 *p;
	Shop_9();
	//修改架构设计，让Product对象，可以被替换，提高可测性
	Shop_9(BaseProduct_9 *pp){
		p=pp;
	};
	int total_9(int id, int number);
};
//计算商品总价，price换成了id，修改为从id获取price
int Shop_9::total_9(int id, int number) {
	int price = p->getPrice(id);
	if (price < 0)
		return -1;
	else if (number < 0)
		return -1;
	else
		return price * number;
}


//生成Mock类
class MOCK_Product : public BaseProduct_9 {
public:
	MOCK_METHOD1(getPrice,int(int id));
};

//修改我们的测试用例
TEST(total_9,price1) {
	BaseProduct_9 *bp=new Product_9();
	Shop_9 dd(bp);
	EXPECT_EQ(100, dd.total_9(1,10));
	EXPECT_EQ(100, dd.total_9(2,5));
	EXPECT_EQ(100, dd.total_9(5,2));
	EXPECT_EQ(100, dd.total_9(10,1));
}
TEST(total_9,price_zero) {
	BaseProduct_9 *bp=new Product_9();
		Shop_9 dd(bp);
	EXPECT_EQ(0, dd.total_9(1001,10));
	EXPECT_EQ(0, dd.total_9(10,0));
}
TEST(total_9,price_negative) {
	BaseProduct_9 *bp=new Product_9();
		Shop_9 dd(bp);
	EXPECT_EQ(-1, dd.total_9(100001,10));
	EXPECT_EQ(-1, dd.total_9(10,-1));
	EXPECT_EQ(-1, dd.total_9(-10,-1));
}

class ShopTest_9: public ::testing::Test {
public:
	Shop_9 *dd;
	BaseProduct_9 *bp;
	MOCK_Product *m;
	static void SetUpTestCase() {
		cout << "SetUpTestCase" << endl;
	}
	void SetUp() {
		bp=new Product_9;
		m=new MOCK_Product;
		dd = new Shop_9(bp);
	}
	void TearDown() {
		delete dd;
		delete bp;
		delete m;
	}
	static void TearDownTestCase() {
		cout << "TearDownTestCase" << endl;
	}
};
TEST_F(ShopTest_9,price1) {
	EXPECT_EQ(100, dd->total_9(1,10));
	EXPECT_EQ(100, dd->total_9(2,5));
	EXPECT_EQ(100, dd->total_9(5,2));
	EXPECT_EQ(100, dd->total_9(10,1));
}
TEST_F(ShopTest_9,price_zero) {
	EXPECT_EQ(0, dd->total_9(1001,10));
	EXPECT_EQ(0, dd->total_9(10,0));
}


//增加新的测试用例，假设price返回的内容会发生变更
TEST_F(ShopTest_9,price_zero_below) {
	dd=new Shop_9((BaseProduct_9*)m);
	EXPECT_CALL(*m,getPrice(11)).WillRepeatedly(Return(2));
	EXPECT_EQ(20, dd->total_9(11,10));
	EXPECT_EQ(0, dd->total_9(11,0));
}
TEST_F(ShopTest_9,price_normal) {
	dd=new Shop_9((BaseProduct_9*)m);
	//使用通配matcher
	EXPECT_CALL(*m,getPrice(_)).WillOnce(Return(2));
	EXPECT_EQ(4, dd->total_9(20,2));
	EXPECT_EQ(6, dd->total_9(30,3));
}
